/**
 * TDS PEC 4
 * Grupo 3H2M
 *
 * El paquete <code>edu.uoc.tds.pec4.server.bbdd</code> agrupa todas las clases
 * que encapsulan los objetos de acceso a datos (DAO),para realizar el acceso
 * a datos. La base de datos es PostgreSQL.
 */
package edu.uoc.tds.pec4.server.bbdd;

import edu.uoc.tds.pec4.beans.AulaDTO;
import edu.uoc.tds.pec4.beans.CFisicaDTO;
import edu.uoc.tds.pec4.common.util.Constantes;
import edu.uoc.tds.pec4.server.bbdd.exceptions.DataBaseDAOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * La clase <code>AulaDAO</code> es el componente de software que suministra
 * la implementación relacionada con la gestión de mantenimiento
 * del subsistema Aulas.<br />
 * Extiende la clase <code>DataBaseDAO</code><br />
 *
 * @author	Luis Rivas Mariño
 * @version	06/12/2011
 * @since	1.00
 * @see         edu.uoc.tds.pec4.server.bbdd.exceptions.DataBaseDAOException
 */
public class AulaDAO extends DataBaseDAO implements IAulaDAO {

    /**
     * Declaramos los PreparedStatement de las consultas a realizar
     * 
     */
    private PreparedStatement pstmtAltaAula;
    private PreparedStatement pstmtBajaLAula;
    private PreparedStatement pstmtModificaAula;
    private PreparedStatement pstmtCFisicaAula;
    private PreparedStatement pstmtAltaLAula;

    /**
     * Constructor de la clase, invoca al constructor de la superclase.
     *
     * @throws  DataBaseDAOException En caso de generarse una excepción de acceso
     *          a la base de datos se dispara al nivel superior
     */
    public AulaDAO() throws DataBaseDAOException {
        super();

        pstmtAltaAula = super.preparedStatement("INSERT INTO aula (nombre,descripcion,"
                + "direccion,idciudad,superficie,aforo,preciohora,preciodia,"
                + "porcentcancelacion,coordgpsx,coordgpsy,plano)"
                + " VALUES(?,?,?,?,?,?,?,?,?,?,?,?) RETURNING idaula");

        pstmtBajaLAula = super.preparedStatement("UPDATE aula SET inactivo=1 WHERE idaula=?");

        pstmtAltaLAula = super.preparedStatement("UPDATE aula SET inactivo=0 WHERE idaula=?");

        pstmtModificaAula = super.preparedStatement("UPDATE aula SET nombre=?, descripcion=?,"
                + "direccion=?,idciudad=?,superficie=?,aforo=?,preciohora=?,preciodia=?,"
                + "porcentcancelacion=?,coordgpsx=?,coordgpsy=?,plano=?,inactivo=?"
                + " WHERE idaula=?");

        pstmtCFisicaAula = super.preparedStatement("INSERT INTO cfisicaaula (idaula, idcfisica) VALUES(?,?)");

    }

    /**
     * Realiza el alta de un aula en la base de datos.
     * @param aula El aula a dar de alta en la base de datos
     * @throws  DataBaseDAOException En caso de generarse una excepción de acceso
     *          a la base de datos se dispara al nivel superior
     */
    @Override
    public int altaAula(AulaDTO aula) throws DataBaseDAOException {

        int id;

        if (aula == null) {
            throw new DataBaseDAOException(DataBaseDAOException.AULA_NULA);
        }

        try {

            // Nueva transacción
            super.setAutoCommit(false);

            // Insertamos el aula
            pstmtAltaAula.clearParameters();

            pstmtAltaAula.setString(1, aula.getNomAula());
            pstmtAltaAula.setString(2, aula.getDescripcion());
            pstmtAltaAula.setString(3, aula.getDireccion());
            pstmtAltaAula.setInt(4, aula.getIdCiudad());
            pstmtAltaAula.setDouble(5, aula.getSuperficie());
            pstmtAltaAula.setInt(6, aula.getAforo());
            pstmtAltaAula.setDouble(7, aula.getPrecioHora());
            pstmtAltaAula.setDouble(8, aula.getPrecioDia());
            pstmtAltaAula.setDouble(9, aula.getPorcentCancelacion());
            pstmtAltaAula.setDouble(10, aula.getCoordGpsX());
            pstmtAltaAula.setDouble(11, aula.getCoordGpsY());
            pstmtAltaAula.setString(12, aula.getPlano());

            // Lanzamos la consulta contra la BBDD
            ResultSet objRS = pstmtAltaAula.executeQuery();

            if (!objRS.next()) {
                // Lanzamos un error avisando que la secuencia no ha devuelto valor
                throw new DataBaseDAOException(DataBaseDAOException.ERROR_OBTENER_SECUENCIA_AULA);
            }
            //Recuperamos el identificador asignado al aula
            id = objRS.getInt(1);

            objRS.close();
            super.commit();

        } catch (SQLException SQLe) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_ALTA_AULA
                    + Constantes.SL + SQLe.getMessage());

        } finally {
            super.setAutoCommit(true);
        }
        return id;
    }

    /**
     * Realiza la baja lógica de un aula en la base de datos.
     * @param aula El aula a dar de baja lógica
     * @throws  DataBaseDAOException En caso de generarse una excepción de acceso
     *          a la base de datos se dispara al nivel superior
     */
    @Override
    public void bajaAula(int idAula) throws DataBaseDAOException {
        try {

            // Nueva transacción
            super.setAutoCommit(false);

            // Damos de baja lógica el aula
            pstmtBajaLAula.clearParameters();
            pstmtBajaLAula.setInt(1, idAula);

            pstmtBajaLAula.execute();
            super.commit();

        } catch (SQLException SQLe) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_BAJA_AULA
                    + Constantes.SL + SQLe.getMessage());
        } finally {
            super.setAutoCommit(true);
        }
    }

    /**
     * Realiza la consulta de un aula
     * @param idAula
     * @return
     * @throws DataBaseDAOException 
     */
    @Override
    public AulaDTO consultaAula(int idAula) throws DataBaseDAOException {

        AulaDTO aula = new AulaDTO();

        try {
            //Construcción de la consulta
            String consulta = "SELECT * FROM aula WHERE idAula = " + idAula;

            //Ejecución de la consulta
            ResultSet rs = super.obtenerConsulta(consulta);
            if (rs.next()) {

                //Obtención de los datos del equipamiento
                aula.setIdAula(rs.getInt("idAula"));
                aula.setNomAula(rs.getString("nombre"));
                aula.setDescripcion(rs.getString("descripcion"));
                aula.setDireccion(rs.getString("direccion"));
                aula.setIdCiudad(rs.getInt("idciudad"));
                aula.setSuperficie(rs.getDouble("superficie"));
                aula.setAforo(rs.getInt("aforo"));
                aula.setPrecioHora(rs.getDouble("preciohora"));
                aula.setPrecioDia(rs.getDouble("preciodia"));
                aula.setPorcentCancelacion(rs.getDouble("porcentCancelacion"));
                aula.setCoordGpsX(rs.getDouble("coordGPSX"));
                aula.setCoordGpsY(rs.getDouble("coordGPSY"));
                aula.setPlano(rs.getString("plano"));
                aula.setInactivo(rs.getInt("inactivo"));
            }

            //Liberación de recursos
            rs.close();
            rs = null;

        } catch (SQLException SQLe) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_CONSULTA_AULA
                    + Constantes.SL + SQLe.getMessage());
        } finally {
            super.setAutoCommit(true);
        }
        return aula;
    }

    /**
     * Realiza la consulta de los datos de un aula en la base de datos a partir de su nombre
     * @param nombre El nombre del aula a consultar
     * @throws DataBaseDAOException
     */
    @Override
    public AulaDTO consultaAulaNombre(String nombre) throws DataBaseDAOException {
        AulaDTO aula = new AulaDTO();
        if (nombre == null) {
            throw new DataBaseDAOException(DataBaseDAOException.NOMBRE_AULA_NULA);
        }
        try {
            // Nueva transacción
            super.setAutoCommit(false);

            //Construcción de la consulta
            String consulta = "SELECT * FROM aula WHERE nombre = '" + nombre + "'";

            //Ejecución de la consulta
            ResultSet rs = super.obtenerConsulta(consulta);
            rs.next();

            if (rs.next()) {
                //Obtención de los datos del aula
                aula.setIdAula(rs.getInt("idaula"));
                aula.setDescripcion(rs.getString("descripcion"));
                aula.setIdCiudad(rs.getInt("idciudad"));
                aula.setSuperficie(rs.getDouble("superficie"));
                aula.setAforo(rs.getInt("aforo"));
                aula.setPrecioHora(rs.getDouble("preciohora"));
                aula.setPrecioDia(rs.getDouble("preciodia"));
                aula.setPorcentCancelacion(rs.getDouble("porcentcancelacion"));
                aula.setCoordGpsX(rs.getDouble("coordgpsx"));
                aula.setCoordGpsY(rs.getDouble("coordgpsy"));
                aula.setPlano(rs.getString("plano"));
                aula.setInactivo(rs.getInt("inactivo"));
            }
            //Liberación de recursos
            rs.close();
            rs = null;

        } catch (SQLException SQLe) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_CONSULTA_AULA
                    + Constantes.SL + SQLe.getMessage());
        } finally {
            super.setAutoCommit(true);
        }

        return aula;
    }

    /**
     * Realiza la modificación de los datos de un aula en la base de datos
     * @param aula El aula a modificar
     * @throws DataBaseDAOException
     */
    @Override
    public void modificaAula(AulaDTO aula) throws DataBaseDAOException {

        if (aula == null) {
            throw new DataBaseDAOException(DataBaseDAOException.AULA_NULA);
        }

        try {
            // Nueva transacción
            super.setAutoCommit(false);

            // Modificamos el equipamiento
            pstmtModificaAula.clearParameters();
            pstmtModificaAula.setString(1, aula.getNomAula());
            pstmtModificaAula.setString(2, aula.getDescripcion());
            pstmtModificaAula.setString(3, aula.getDireccion());
            pstmtModificaAula.setInt(4, aula.getIdCiudad());
            pstmtModificaAula.setDouble(5, aula.getSuperficie());
            pstmtModificaAula.setInt(6, aula.getAforo());
            pstmtModificaAula.setDouble(7, aula.getPrecioHora());
            pstmtModificaAula.setDouble(8, aula.getPrecioDia());
            pstmtModificaAula.setDouble(9, aula.getPorcentCancelacion());
            pstmtModificaAula.setDouble(10, aula.getCoordGpsX());
            pstmtModificaAula.setDouble(11, aula.getCoordGpsY());
            pstmtModificaAula.setString(12, aula.getPlano());
            pstmtModificaAula.setInt(13, aula.getInactivo());
            pstmtModificaAula.setInt(14, aula.getIdAula());

            pstmtModificaAula.execute();
            super.commit();

        } catch (SQLException SQLe) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_MODIFICACION_AULA
                    + Constantes.SL + SQLe.getMessage());

        } finally {
            super.setAutoCommit(true);
        }
    }

    /**
     * Realiza la asignación de una lista de características físicas a un aula
     * @param listaCFisicas es la lista de características físicas a asignar
     * @param idAula El identificador del aula 
     * @throws DataBaseDAOException
     */
    public void cFisicaToAula(List<CFisicaDTO> listaCFisicas, int idAula) throws DataBaseDAOException {

        try {
            // Nueva transacción
            super.setAutoCommit(false);

            // Actualizamos el cc del cliente
            pstmtCFisicaAula.clearParameters();

            for (CFisicaDTO cFisica : listaCFisicas) {
                pstmtCFisicaAula.setInt(1, idAula);
                pstmtCFisicaAula.setInt(2, cFisica.getIdCFisica());
                pstmtCFisicaAula.execute();
            }

            super.commit();

        } catch (SQLException SQLe) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_CFISICA_AULA
                    + Constantes.SL + SQLe.getMessage());

        } finally {
            //super.setAutoCommit(true);
        }
    }

    /**
     * Realiza la activación de un equipamiento que estaba en baja lógica
     * @param idEquipamiento El identificador del equipamiento a activar
     * @throws RemoteException
     * @throws GestorMantenimientoException 
     */
    @Override
    public void activaAula(int idAula) throws DataBaseDAOException {

        try {
            // Nueva transacción
            super.setAutoCommit(false);

            // Reactivamos el equipamiento
            pstmtAltaLAula.clearParameters();
            pstmtAltaLAula.setInt(1, idAula);

            pstmtAltaLAula.execute();
            super.commit();

        } catch (SQLException SQLe) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_ALTALOGICA_AULA
                    + Constantes.SL + SQLe.getMessage());

        } finally {
            super.setAutoCommit(true);
        }
    }

    /**
     * Obtiene la lista de características físicas existentes en la base de datos
     * @return cFisicas La lista de las características físicas existentes en la
     *         base de datos
     */
    public List<CFisicaDTO> cFisicasAula() throws DataBaseDAOException {

        List<CFisicaDTO> cFisicas = new ArrayList<CFisicaDTO>();

        try {
            // Nueva transacción
            super.setAutoCommit(false);

            //Construcción de la consulta
            String eSQL = "SELECT * FROM cfisica ORDER BY idcfisica";

            //Se ejecuta la consulta a la base de datos
            ResultSet rs = super.obtenerConsulta(eSQL);

            //Recorrido del ResulSet para rellenar el vector
            while (rs.next()) {
                CFisicaDTO cf = new CFisicaDTO();

                cf.setIdCFisica(rs.getInt("idcfisica"));
                cf.setNomCFisica(rs.getString("nombre"));
                cFisicas.add(cf);
            }

            //Se liberan recursos
            rs.close();
            rs = null;

        } catch (SQLException eqS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_CFISICA_BBDD
                    + Constantes.SL + eqS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_MAESTROS_MANTENIMIENTO_GENERAL
                    + Constantes.SL + eE.getMessage());
        } finally {
            super.setAutoCommit(true);
        }

        return cFisicas;

    }

     /**
     * Obtiene la lista de características físicas existentes en la base de datos
     * @param idAula El identificador del aula
     * @return lcFisicas La lista de las características físicas existentes en el aula
     */
    public List<CFisicaDTO> cFisicasFromAula(int idAula) throws DataBaseDAOException {
        
         List<CFisicaDTO> lcFisicas = new ArrayList<CFisicaDTO>();

        try {
            // Nueva transacción
            super.setAutoCommit(false);

            //Construcción de la consulta
            String sql = "SELECT a.idaula, b.nombre,a.idcfisica FROM cfisicaaula AS a, "
            + "cfisica AS b WHERE a.idcfisica = b.idcfisica AND a.idaula=" + idAula;
            
            //Se ejecuta la consulta a la base de datos
            ResultSet rs = super.obtenerConsulta(sql);

            //Recorrido del ResulSet para rellenar el vector
            while (rs.next()) {
                CFisicaDTO cf = new CFisicaDTO();

                cf.setIdCFisica(rs.getInt("idcfisica"));
                cf.setNomCFisica(rs.getString("nombre"));
                lcFisicas.add(cf);
            }

            //Se liberan recursos
            rs.close();
            rs = null;

            super.commit();

        } catch (SQLException eqS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_CFISICA_BBDD
                    + Constantes.SL + eqS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_MAESTROS_MANTENIMIENTO_GENERAL
                    + Constantes.SL + eE.getMessage());
        } finally {
            super.setAutoCommit(true);
        }

        return lcFisicas;

    }
    
    /* Llama al método de la clase padre para liberar recursos
     * @see java.lang.Object#finalize() 
     */
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
    }
}
